<template>
	<view class="tn-tabs-class tn-tabs" :class="[backgroundColorClass]"
		:style="{backgroundColor: backgroundColorStyle, marginTop: $t.string.getLengthUnitValue(top, 'px')}">

		<!-- _tgetRect()对组件根节点无效，因为写了.in(this)，故这里获取内层接点尺寸 -->
		<view :id="id">
			<scroll-view scroll-x class="tn-tabs__scroll-view" :scroll-left="scrollLeft" scroll-with-animation>
				<view class="tn-tabs__scroll-view__box" :class="{'tn-tabs__scroll-view--flex': !isScroll}">
					<!-- item -->
					<view class="my-item" :class="flexType" v-for="(item, index) in list" :key="index" :style="[tabItemStyle(index)]">
						<view :id="'tn-tabs__scroll-view__item-' + index"
							class="tn-tabs__scroll-view__item tn-text-ellipsis" @tap="clickTab(index)">
							{{ item[name] || item['name'] }}
						</view>
						<view class="number tn-text-ellipsis" v-if="item[count] || item['count']">
							{{ countNum(item) || '0' }}</view>
					</view>
					<!-- 底部滑块 -->
					<view v-if="showBar" class="tn-tabs__bar" :style="[tabBarStyle]"></view>
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
	import componentsColor from '../../libs/mixin/components_color.js'
	export default {
		mixins: [componentsColor],
		name: 'tn-tabs',
		props: {
			// 标签列表
			list: {
				type: Array,
				default () {
					return []
				}
			},
			// 列表数据tab名称的属性
			name: {
				type: String,
				default: 'name'
			},
			// 列表数据微标数量的属性
			count: {
				type: String,
				default: 'count'
			},
			// 当前活动的tab索引
			current: {
				type: Number,
				default: 0
			},
			// 菜单是否可以滑动
			isScroll: {
				type: Boolean,
				default: true
			},
			// 高度
			height: {
				type: Number,
				default: 80
			},
			// 距离顶部的距离(px)
			top: {
				type: Number,
				default: 0
			},
			// item的宽度
			itemWidth: {
				type: [String, Number],
				default: 'auto'
			},
			// 过渡动画时长
			duration: {
				type: Number,
				default: 0.3
			},
			// 选中时的颜色
			activeColor: {
				type: String,
				default: '#01BEFF'
			},
			// 未被选中时的颜色
			inactiveColor: {
				type: String,
				default: '#080808'
			},
			// 选中的item样式
			activeItemStyle: {
				type: Object,
				default () {
					return {}
				}
			},
			// 是否显示底部滑块
			showBar: {
				type: Boolean,
				default: true
			},
			// 底部滑块的宽度
			barWidth: {
				type: Number,
				default: 40
			},
			// 底部滑块的高度
			barHeight: {
				type: Number,
				default: 6
			},
			// 自定义底部滑块的样式
			barStyle: {
				type: Object,
				default () {
					return {}
				}
			},
			// 单个tab的左右内边距
			gutter: {
				type: Number,
				default: 30
			},
			// 微标的偏移数[top, right]
			badgeOffset: {
				type: Array,
				default () {
					return [20, 30]
				}
			},
			// 是否加粗字体
			bold: {
				type: Boolean,
				default: false
			},
			
			//数量和名称的排列方式
			flexType:{
				type: String,
				default: ''
			}
		},
		computed: {
			// 底部滑块样式
			tabBarStyle() {
				let style = {
					width: this.$t.string.getLengthUnitValue(this.barWidth),
					height: this.$t.string.getLengthUnitValue(this.barHeight),
					borderRadius: `${this.barHeight / 2}rpx`,
					backgroundColor: this.activeColor,
					opacity: this.barMoveFirst ? 0 : 1,
					transform: `translate(${this.scrollBarLeft}px, -100%)`,
					transitionDuration: this.barMoveFirst ? '0s' : `${this.duration}s`
				}
				Object.assign(style, this.barStyle)
				return style
			},
			// tabItem样式
			tabItemStyle() {
				return index => {
					let style = {
						width: this.$t.string.getLengthUnitValue(this.itemWidth),
						// height: this.$t.string.getLengthUnitValue(this.height),
						lineHeight: this.$t.string.getLengthUnitValue(this.height / 2),
						fontSize: this.fontSizeStyle || '28rpx',
						padding: this.isScroll ? `0 ${this.gutter}rpx` : '',
						flex: this.isScroll ? 'auto' : '1',
						transitionDuration: `${this.duration}s`,
						textAlign: 'center'
					}
					if (index === this.currentIndex) {
						if (this.bold) {
							style.fontWeight = 'bold'
						}
						style.color = this.activeColor
						Object.assign(style, this.activeItemStyle)
					} else {
						style.color = this.inactiveColor
					}
					return style
				}
			},
			countNum() {
				return item => {
					let count = parseFloat(item['count']).toFixed(0)
					return this.flexType? `(${count})` : count
				}
			}
		},
		data() {
			return {
				// id值
				id: this.$t.uuid(),
				// 滚动scroll-view的左边距离
				scrollLeft: 0,
				// 存放查询后tab菜单的节点信息
				tabQueryInfo: [],
				// 组件宽度
				componentWidth: 0,
				// 底部滑块的移动距离
				scrollBarLeft: 0,
				// 组件到屏幕左边的巨鹿
				componentLeft: 0,
				// 当前选中的itemIndex
				currentIndex: this.current,
				// 标记底部滑块是否第一次移动，第一次移动的时候不触发动画
				barMoveFirst: true
			}
		},
		watch: {
			// 监听tab的变化，重新计算tab菜单信息
			list(newValue, oldValue) {
				// list变化时，重置内部索引，防止出现超过数据边界的问题
				if (newValue.length !== oldValue.length) this.currentIndex = 0
				this.$nextTick(() => {
					this.init()
				})
			},
			current: {
				handler(val) {
					this.$nextTick(() => {
						this.currentIndex = val
						this.scrollByIndex()
					})
				},
				immediate: true
			}
		},
		mounted() {
			this.init()
		},
		methods: {
			// 初始化变量
			async init() {
				// 获取tabs组件的信息
				let tabRect = await this._tGetRect('#' + this.id)
				// 计算组件的宽度
				this.componentLeft = tabRect.left
				this.componentWidth = tabRect.width
				this.getTabRect()
			},
			// 点击tab菜单
			clickTab(index) {
				if (index === this.currentIndex) return
				this.$emit('change', index)
			},
			// 查询tab的布局信息
			getTabRect() {
				let query = uni.createSelectorQuery().in(this)
				// 遍历所有的tab
				for (let i = 0; i < this.list.length; i++) {
					query.select(`#tn-tabs__scroll-view__item-${i}`).fields({
						size: true,
						rect: true
					})
				}
				query.exec((res) => {
					this.tabQueryInfo = res
					// 初始滚动条和底部滑块的位置
					this.scrollByIndex()
				})
			},
			// 滚动scrollView，让活动的tab处于屏幕中间
			scrollByIndex() {
				// 当前获取tab的布局信息
				let tabInfo = this.tabQueryInfo[this.currentIndex]
				if (!tabInfo) return

				// 活动tab的宽度
				let tabWidth = tabInfo.width
				// 活动item的左边到组件左边的距离
				let offsetLeft = tabInfo.left - this.componentLeft
				// 计算scroll-view移动的距离
				let scrollLeft = offsetLeft - (this.componentWidth - tabWidth) / 2
				this.scrollLeft = scrollLeft < 0 ? 0 : scrollLeft

				// 计算当前滑块需要移动的距离，当前活动item的中点到左边的距离减去滑块宽度的一半
				let left = tabInfo.left + tabInfo.width / 2 - this.componentLeft

				// 计算当前活跃item到组件左边的距离
				this.scrollBarLeft = left - uni.upx2px(this.barWidth) / 2

				// 防止在计算时出错，所以延迟执行标记不是第一次移动
				if (this.barMoveFirst) {
					setTimeout(() => {
						this.barMoveFirst = false
					}, 100)
				}
			}
		}
	}
</script>

<style lang="scss" scoped>
	/* #ifndef APP-NVUE */
	::-webkit-scrollbar {
		display: none;
		width: 0 !important;
		height: 0 !important;
		-webkit-appearance: none;
		background: transparent;
	}

	/* #endif */

	/* #ifdef H5 */
	// 通过样式穿透，隐藏H5下，scroll-view下的滚动条
	scroll-view ::v-deep ::-webkit-scrollbar {
		display: none;
		width: 0 !important;
		height: 0 !important;
		-webkit-appearance: none;
		background: transparent;
	}

	/* #endif */

	.tn-tabs {
		&__scroll-view {
			position: relative;
			width: 100%;
			white-space: nowrap;

			&__box {
				justify-content: space-between;
				display: flex;
				position: relative;
				/* #ifdef MP-TOUTIAO */
				white-space: nowrap;
				/* #endif */
			}

			&__item {
				position: relative;
				/* #ifndef APP-NVUE */
				display: inline-block;
				/* #endif */
				text-align: center;
				transition-property: background-color, color;

			}

			&--flex {
				display: flex;
				flex-direction: row;
				justify-content: space-between;
			}
		}

		&__bar {
			position: absolute;
			bottom: -5rpx;
		}

		.number {
			max-width: 100%;
		}

		.my-item {
			padding: 10rpx 0;
		}

		.flex-row {
			display: flex;
			align-items: center;
			justify-content: center;
			height: 80rpx;
		}
	}
</style>